package com.xy.etl.log;


import ch.qos.logback.classic.spi.LoggingEvent;
import ch.qos.logback.core.rolling.RollingFileAppender;
import ch.qos.logback.core.spi.DeferredProcessingAware;
import cn.hutool.core.date.DateUtil;

import java.io.File;
import java.io.FileWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


/**
 * 自定义的appender
 * 1.可以对接受到的event中的日志信息做任何操作处理
 * 2.可以在同步写日志文件的时候，存入MySQL或者es
 *
 * @author liubq
 * @version V1.0
 **/
public class ElcLogFileAppender<E> extends RollingFileAppender<E> {

    private String filePath;

    public String getFilePath() {
        return filePath;
    }

    public void setFilePath(String filePath) {
        this.filePath = filePath;
    }

    //执行线程
    private static ExecutorService es = Executors.newSingleThreadExecutor();
    //文件名称
    private static Map<String, Map<String, FileWriter>> writeLogMap = new HashMap<>();

    /**
     * 取得名称
     *
     * @param logName
     * @return
     */
    private static synchronized FileWriter getWriter(String moduleName, String logName) {
        //日期
        String nowDate = DateUtil.format(new Date(), "yyyyMMdd");
        //不包含，就是新的一天，清理掉旧的数据
        if (!writeLogMap.containsKey(nowDate)) {
            for (Map<String, FileWriter> writeMap : writeLogMap.values()) {
                for (FileWriter w : writeMap.values()) {
                    try {
                        w.close();
                    } catch (Exception ex) {
                    }
                }
            }
            writeLogMap.clear();
            //添加新的
            writeLogMap.put(nowDate, new HashMap<>());
        }
        try {
            Map<String, FileWriter> logMap = writeLogMap.get(nowDate);
            if (logMap == null) {
                logMap = new HashMap<>();
            }
            FileWriter w = logMap.get(logName);
            if (w == null) {
                File file = new File("/home/business/" + moduleName + "/" + logName + ".log");
                if (!file.exists()) {
                    file.setExecutable(true);
                    file.setWritable(true);
                    file.setReadable(true);
                    file.getParentFile().mkdirs();
                    file.createNewFile();
                }
                // 使用FileWriter构造函数创建文件输出流
                w = new FileWriter(file, true);
                logMap.put(logName, w);

            }
            return w;
        } catch (Exception ex) {
            ex.printStackTrace();
            System.out.println("创建日志文件(/home/business/" + moduleName + "/" + logName + ".log)失败！");
            throw new RuntimeException(ex);
        }

    }


    /**
     * 添加日志
     *
     * @param moduleName
     * @param logName
     * @param contentList
     */
    private static void append(final String moduleName, final String logName, final String... contentList) {
        if (logName == null || logName.length() == 0) {
            return;
        }
        if (contentList == null || contentList.length == 0) {
            return;
        }
        //提交，包装顺序执行
        es.submit(() -> {
            try {
                FileWriter w = getWriter(moduleName, logName);
                if (w != null) {
                    SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
                    String date = f.format(new Date());
                    StringBuilder sb = new StringBuilder();
                    for (String content : contentList) {
                        sb.append(date).append(" ").append(content).append("\r\n");
                    }
                    w.write(sb.toString());
                    w.flush();
                }
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        });
    }


    /**
     * 文件名称
     *
     * @return
     */
    private String getFileName() {
        String selfCode = EtlLog.getLogNote();
        if (selfCode == null || selfCode.trim().length() == 0) {
            return null;
        }
        int e = selfCode.indexOf("]");
        if (e > 0) {
            return selfCode.trim().substring(1, e);
        } else {
            return selfCode;
        }
    }

    /**
     * 覆盖父类OutputStreamAppender的日志记录功能，再这里面做日志切操作功能
     *
     * @param event
     */
    protected void subAppend(E event) {
        if (event == null) {
            return;
        }
        super.subAppend(event);
        try {
            if (event instanceof DeferredProcessingAware) {
                ((DeferredProcessingAware) event).prepareForDeferredProcessing();
            }
            String msg = null;
            if (event instanceof LoggingEvent) {
                msg = ((LoggingEvent) event).getMessage();
            } else {
                msg = event.toString();
            }
            //根据标签规则拿到日志字符串，这里可以再次修改日志信息
            append(getFilePath(), getFileName(), msg);
        } catch (Exception var3) {
            var3.printStackTrace();
        }
    }

}
